package com.yc.project2.myjunit.framework;

import com.yc.project2.myjunit.annotions.*;
import org.apache.log4j.Logger;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

/**
 * 读取单元测试类  以反射方式获取这个测试类中所有方法  区分注解
 * 以对应的顺序来调用即可
 *
 * @author zwei
 * @create 2024-07-26 16:39
 */
public class MyJunitRunner {
    private static Logger logger = Logger.getLogger(MyJunitRunner.class);

    public static void run(Class cls) {
        //反射执行
        List<Method> beforeMethods = new ArrayList<>();
        List<Method> beforeClassMethods = new ArrayList<>();
        List<Method> testMethods = new ArrayList<>();
        List<Method> ignoreMethods = new ArrayList<>();
        List<Method> afterMethods = new ArrayList<>();
        List<Method> afterClassMethods = new ArrayList<>();
        //1.取出cls中的所有方法
        Method[] methods = cls.getDeclaredMethods();
        for (Method m : methods) {
            Annotation[] ans = m.getAnnotations();//取出这个方法上的所有注解
            for (Annotation a : ans) {
                logger.debug("当前方法为：" + m.getName() + ",方法上的注解：" + a.toString());
                if (a instanceof MyBeforeClass) {
                    beforeClassMethods.add(m);
                } else if (a instanceof MyBefore) {
                    beforeMethods.add(m);
                } else if (a instanceof MyAfter) {
                    afterMethods.add(m);
                } else if (a instanceof MyAfterClass) {
                    afterClassMethods.add(m);
                } else if (a instanceof MyIgnore) {
                    ignoreMethods.add(m);
                } else if (a instanceof MyTest) {
                    testMethods.add(m);
                }
            }
        }
        try {
            //已上完成了单元测试类的解析
            //按生命周期顺序调用
            //1.调用所有@MyBeforeClass
            for (Method m:beforeClassMethods){
                m.invoke(null);
            }
            //循环所有的@Test的方法
            for (Method testMethod:testMethods){
                //@构造
                Object obj=cls.newInstance();
                //Before
                for (Method  beforeMethod:beforeMethods){
                    beforeMethod.invoke(obj);
                }
                //test
                testMethod.invoke(obj);
                //after
                for (Method afterMethod:afterMethods){
                    afterMethod.invoke(obj);
                }
            }
            for (Method m:afterClassMethods){
                m.invoke(null);
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}
